﻿Imports System.Threading.Tasks

Namespace GestionCalculs
    ''' <summary>
    ''' Fonction Calcul Racine
    ''' </summary>
    ''' <remarks></remarks>
    Public Class FonctionCalculRacine
        Inherits FonctionCalcul
        Implements IFonctionCalculComposee
        Protected _lFonctionsCalculIntermediaires As IList

        Public Shared Property EnableParallelism As Boolean = False

#Region "Constructeur"
        ''' <summary>
        ''' Constructeur
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New(ByVal modeRecalcul As TypeRecalcul)
            MyBase.New(modeRecalcul)
            _lFonctionsCalculIntermediaires = New List(Of IFonctionCalcul)
        End Sub
#End Region
#Region "Propriétés"
        ''' <summary>
        ''' Mode de recalcul
        ''' </summary>
        ''' <remarks></remarks>
        Public Overrides Property ModeRecalcul() As TypeRecalcul
            Get
                Return MyBase.ModeRecalcul
            End Get
            Set(ByVal value As TypeRecalcul)
                If value <> _modeRecalcul Then
                    If value = TypeRecalcul.Automatique Then
                        If EtatCalcul = ValueEtatCalcul.A_MAJ Then Calculer()
                        For Each fonctionCalculIntermediare As IFonctionCalcul In _lFonctionsCalculIntermediaires
                            fonctionCalculIntermediare.ModeRecalcul = TypeRecalcul.Automatique
                        Next
                    End If
                    _modeRecalcul = value
                    RaiseEventModeRecalculChanged(Me, New EventArgs)
                End If
            End Set
        End Property
#End Region
#Region "Méthodes Calcul / gestion des fonctions intermédiaires"
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Public Overrides Sub Calculer(Optional ByVal ForcerCalcul As Boolean = False)
            If EtatCalcul <> ValueEtatCalcul.NON_INITIALISE Or ForcerCalcul = True Then
                If EnableParallelism Then

                    Dim func = Sub(c As IFonctionCalcul)
                                   If c.EtatCalcul = ValueEtatCalcul.A_MAJ Then
                                       c.Calculer()
                                   End If
                               End Sub

                    Dim work = Parallel.ForEach(Of IFonctionCalcul)( _
                         CType(_lFonctionsCalculIntermediaires, IEnumerable(Of IFonctionCalcul)), _
                         func)


                Else
                    For Each fonctionImpactante As IFonctionCalcul In _lFonctionsCalculIntermediaires
                        If fonctionImpactante.EtatCalcul = ValueEtatCalcul.A_MAJ Then
                            fonctionImpactante.Calculer()
                        End If
                    Next
                End If

                _etatCalcul.Value = ValueEtatCalcul.A_JOUR
                RaiseEventAfterCalculer(Me, New EventArgs)
            End If
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub AjouteFonctionCalculIntermediaire(ByVal value As IFonctionCalcul) Implements IFonctionCalculComposee.AjouteFonctionCalculIntermediaire
            _lFonctionsCalculIntermediaires.Add(value)
            AddHandler value.AfterInvalider, AddressOf onFonctionCalculIntermediaire_ApresInvalider
            AddHandler value.EtatCalculChanged, AddressOf onFonctionCalculIntermediaire_ApresModifEtatCalcul
            AddHandler value.ModeRecalculChanged, AddressOf onFonctionCalculIntermediaire_ApresModifModeRecalcul
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub RetireFonctionCalculIntermediaire(ByVal value As IFonctionCalcul) Implements IFonctionCalculComposee.RetireFonctionCalculIntermediaire
            RemoveHandler value.AfterInvalider, AddressOf onFonctionCalculIntermediaire_ApresInvalider
            RemoveHandler value.EtatCalculChanged, AddressOf onFonctionCalculIntermediaire_ApresModifEtatCalcul
            RemoveHandler value.ModeRecalculChanged, AddressOf onFonctionCalculIntermediaire_ApresModifModeRecalcul
            _lFonctionsCalculIntermediaires.Remove(value)
        End Sub
        ''' <summary>
        ''' Liste des fonctions de calcul intermédiaires
        ''' </summary>
        ''' <remarks></remarks>
        Public Function ListeFonctionsCalculIntermediaires() As IEnumerable Implements IFonctionCalculComposee.ListeFonctionsCalculIntermediaires
            Return _lFonctionsCalculIntermediaires
        End Function
#End Region
#Region "Interception des évènements extérieurs / Gestion des modifs d'un calcul intermédiaire"

        Private Sub onFonctionCalculIntermediaire_ApresInvalider(ByVal sender As Object, ByVal e As EventArgs)
            Me.Invalider()
        End Sub
        Private Sub onFonctionCalculIntermediaire_ApresModifEtatCalcul(ByVal sender As Object, ByVal e As EventArgs)
            Dim fonctionModifiee As FonctionCalcul = CType(sender, FonctionCalcul)
            If fonctionModifiee.EtatCalcul = ValueEtatCalcul.NON_INITIALISE Then
                'Une fonction impactante est devenue non calculable
                Me.EstNonCalculable()
            End If
        End Sub
        Private Sub onFonctionCalculIntermediaire_ApresModifModeRecalcul(ByVal sender As Object, ByVal e As EventArgs)
            Dim fonctionModifiee As FonctionCalcul = CType(sender, FonctionCalcul)
            If fonctionModifiee.ModeRecalcul = TypeRecalcul.SurOrdre Then
                'Le mode de recalcul de l'une des fonctions impactantes est passé en sur ordre
                Me.ModeRecalcul = TypeRecalcul.SurOrdre
            End If
        End Sub

#End Region
    End Class
End Namespace
